package com.auth.manager.security.auth;

import cn.hutool.core.util.StrUtil;
import com.auth.manager.security.service.CustomUserDetailsService;
import com.auth.manager.security.service.UserAccount;
import com.auth.manager.utils.JwtTokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;

/**
 * @version 1.0.0
 * @Date: 2022/4/27 20:39
 * @Author ZhuYouBin
 * @Description [用户授权]: 拦截所有的请求url,获取token、校验token
 */
@Component
public class JwtAuthFilter extends OncePerRequestFilter {

    @Autowired
    private CustomUserDetailsService customUserDetailsService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        /**
         * 这个过滤器里面需要处理什么逻辑呢？？？
         * 1、从请求头Header里面, 获取当前请求携带的 token
         * 2、如果没有 token, 则放行过滤器, 因为没有 token 可能是白名单请求, 所以放行请求, 让后面的过滤器继续判断
         * 3、如果有 token, 说明当前请求需要校验
         * 4、校验 token
         * --- 如果 token 为空, 则不处理 token
         * --- 如果 token 不为空, 校验是否合法, 是否过期
         * 5、将 Token 对应的用户信息，放入 Security 上下文对象中,
         * 即：SecurityContextHolder 对象里面, 这样后面的过滤器就可以直接从 SecurityContextHolder 里面获取用户信息, 然后进行登录、授权操作
         */
        // 1、获取请求头 token
        String token = request.getHeader(JwtTokenUtil.TOKEN_NAME);
        // Token 不为空
        // 3、校验 token 是否合法
        if (!StrUtil.isEmpty(token)) {
            try {
                if (!JwtTokenUtil.isTokenValid(token)) {
                    String username = JwtTokenUtil.getUsernameFromToken(token);
                    // 保存用户信息到 SecurityContextHolder
                    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
                    if (StrUtil.isNotBlank(username) && Objects.isNull(authentication)) {
                        // TODO 从数据库或者 Redis 里面获取用户信息
                        UserAccount account = (UserAccount) customUserDetailsService.loadUserByUsername(username);
                        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, null, account.getAuthorities());
                        authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
                    }
                }
            } catch (Exception e) {
                System.out.println("JWT 解析失败......");
                e.printStackTrace();
            }
        }

        // 2、不存在 token, 放行过滤器
        filterChain.doFilter(request, response);
    }

}
